package com.sen.organization.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.sen.common.common.bo.PeopleInfo;
import com.sen.common.common.constrant.CommonConstrant;
import com.sen.common.common.response.MessageResult;
import com.sen.common.common.response.PageVo;
import com.sen.common.common.util.SnowflakeIdWorker;
import com.sen.common.mp.model.CommonBaseModel;
import com.sen.common.user.config.UserContextHolder;
import com.sen.organization.bo.MemberPeopleOrgBO;
import com.sen.organization.bo.SearchPeopleBO;
import com.sen.organization.dto.*;
import com.sen.organization.exception.MemberException;
import com.sen.organization.mapper.*;
import com.sen.organization.model.*;
import com.sen.organization.service.PeopleService;
import com.sen.organization.vo.MemberPeopleListVO;
import com.sen.organization.vo.MemberPeopleVO;
import com.sen.rbac.constant.RbacConstant;
import com.sen.rbac.dto.SysAccountDto;
import com.sen.rbac.feign.RbacAccountFeign;
import lombok.extern.slf4j.Slf4j;
import org.modelmapper.ModelMapper;
import org.springframework.stereotype.Service;
import org.springframework.transaction.support.TransactionTemplate;

import javax.annotation.Resource;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;

import static com.sen.organization.enums.MemberEnum.*;

/**
 * @author esjiang
 */
@Service
@Slf4j
public class PeopleServiceImpl extends ServiceImpl<MemberPeopleDao, MemberPeople> implements PeopleService {

    @Resource
    MemberPeopleDao memberPeopleDao;

    @Resource
    MemberPeopleExtDao memberPeopleExtDao;

    @Resource
    MemberPeopleOrgDao memberPeopleOrgDao;

    @Resource
    ModelMapper modelMapper;

    @Resource
    MemberPeopleAccountDao accountDao;

    @Resource
    RbacAccountFeign rbacAccountFeign;

    @Resource
    TransactionTemplate transactionTemplate;

    @Resource
    MemberDepartmentDao memberDepartmentDao;

    @Resource
    MemberPeopleAccountDao memberPeopleAccountDao;

    @Override
    public PageVo<MemberPeopleListVO> list(MemberPeopleSearchDTO memberPeopleSearchDTO) {
        PageVo<MemberPeopleListVO> peopleVOPageVo = new PageVo<>();
        String cname = memberPeopleSearchDTO.getCname();
        IPage<SearchPeopleBO> pages = memberPeopleDao.listSearchPeople(new Page<>(memberPeopleSearchDTO.getPage(), memberPeopleSearchDTO.getPageSize()),
                cname, UserContextHolder.getPeople().getEntityCode());
        List<SearchPeopleBO> records = pages.getRecords();
        if (CollectionUtil.isNotEmpty(records)) {
            peopleVOPageVo.setList(records.stream().map(record -> modelMapper.map(record, MemberPeopleListVO.class)).collect(Collectors.toList()));
            peopleVOPageVo.setTotal(pages.getTotal());
        }
        return peopleVOPageVo;
    }

    @Override
    public void add(MemberPeopleDTO memberPeopleDTO) {
        /** 检查账户名是否有效 */
        Optional.ofNullable(memberPeopleDTO.getAccount()).map(MemberPeopleAccountDTO::getUserName).ifPresent(userName -> {
            MessageResult checkUniqueAccount = rbacAccountFeign.checkUniqueAccount(userName);
            MessageResult.checkRemoteInvokeResult(checkUniqueAccount);
        });
        Optional.ofNullable(memberPeopleDTO.getAccount()).map(MemberPeopleAccountDTO::getUserName).ifPresent(userName -> {
            /**
             *  写入账户表
             *  */
            SysAccountDto sysAccountDto = new SysAccountDto();
            sysAccountDto.setUserName(userName);
            sysAccountDto.setPassword(memberPeopleDTO.getAccount().getPassword());
            sysAccountDto.setUserType(RbacConstant.user_type_4);
            if(sysAccountDto.getEntityCode()==null) {
                sysAccountDto.setEntityCode(UserContextHolder.getPeople().getEntityCode());
            }
            MessageResult add = rbacAccountFeign.add(sysAccountDto);
            MessageResult.checkRemoteInvokeResult(add);
            transactionTemplate.execute((integer) -> {
                /**2，插入基本信息 */
                if (ObjectUtil.isNotNull(memberPeopleDTO.getBase())) {
                    MemberPeopleBaseInfoDTO base = memberPeopleDTO.getBase();
                    MemberPeople memberPeople = saveBaseInfo(base);
                    /**1，写入账户信息 */
                    Optional.ofNullable(memberPeopleDTO.getAccount()).map(MemberPeopleAccountDTO::getUserName).ifPresent(userName1 ->
                            saveAccountInfo(memberPeopleDTO.getAccount(), memberPeople.getPeopleCode()));
                    ;
                    /**3，插入扩展信息 */
                    Optional.ofNullable(memberPeopleDTO.getExt()).ifPresent(a -> saveExtInfo(memberPeopleDTO.getExt(), memberPeople.getPeopleCode()));
                    /**4，插入部门人员信息  */
                    Optional.ofNullable(memberPeopleDTO.getOrg()).ifPresent(a -> saveOrgInfo(memberPeopleDTO.getOrg(), memberPeople.getPeopleCode()));
                }
                return 1;
            });

        });
    }

    private MemberPeople saveBaseInfo(MemberPeopleBaseInfoDTO memberPeopleBaseInfoDTO) {
        MemberPeople memberPeople = modelMapper.map(memberPeopleBaseInfoDTO, MemberPeople.class);
        /** 设置主体编码 */
        memberPeople.setEntityCode(UserContextHolder.getPeople().getEntityCode());
        memberPeople.setPeopleCode(SnowflakeIdWorker.generateStrId());
        if (memberPeopleDao.insert(memberPeople) != 1) {
            throw new MemberException(people_add_failed);
        }
        return memberPeople;
    }

    private void saveExtInfo(MemberPeopleExtDTO memberPeopleExtDTO, String peopleCode) {
        MemberPeopleExt memberPeopleExt = modelMapper.map(memberPeopleExtDTO, MemberPeopleExt.class);
        memberPeopleExt.setPeopleCode(peopleCode);
        if (memberPeopleExtDao.insert(memberPeopleExt) != 1) {
            throw new MemberException(people_add_failed);
        }
    }

    private void saveOrgInfo(MemberPeopleOrgDTO memberPeopleOrgDTO, String peopleCode) {
        MemberPeopleOrg memberPeopleOrg = modelMapper.map(memberPeopleOrgDTO, MemberPeopleOrg.class);
        memberPeopleOrg.setPeopleCode(peopleCode);
        if (memberPeopleOrgDao.insert(memberPeopleOrg) != 1) {
            throw new MemberException(people_add_failed);
        }
    }

    private void saveAccountInfo(MemberPeopleAccountDTO memberPeopleAccountDTO, String peopleCode) {
        /** 检索人员是否存在 */
        List<MemberPeopleAccount> memberPeopleAccounts = accountDao.selectList(Wrappers.<MemberPeopleAccount>lambdaQuery().eq(MemberPeopleAccount::getUserName, memberPeopleAccountDTO.getUserName()));
        if (CollUtil.isNotEmpty(memberPeopleAccounts)){
            throw new MemberException(people_is_exist) ;
        }
        MemberPeopleAccount memberPeopleAccount = modelMapper.map(memberPeopleAccountDTO, MemberPeopleAccount.class);
        memberPeopleAccount.setPeopleCode(peopleCode);
        if (accountDao.insert(memberPeopleAccount) != 1) {
            throw new MemberException(people_add_failed);
        }
    }

    @Override
    public void upd(MemberPeopleDTO memberPeopleDTO) {
        /** 检索人员是否存在 */
        MemberPeople memberPeople = memberPeopleDao.selectOne(Wrappers.<MemberPeople>lambdaQuery().eq(CommonBaseModel::getId, memberPeopleDTO.getBase().getId()));
        if (ObjectUtil.isNull(memberPeople)) {
            throw new MemberException(people_not_exist);
        }
        /** 1，账户信息不修改 */
        Optional.ofNullable(memberPeopleDTO.getBase()).map(a -> modelMapper.map(a, MemberPeople.class))
                .ifPresent(b -> memberPeopleDao.updateById(b));
        /** 2，基本信息和扩展信息修改 */
        Optional.ofNullable(memberPeopleDTO.getExt()).map(a -> modelMapper.map(a, MemberPeopleExt.class))
                .ifPresent(b -> {
                            memberPeopleExtDao.delete(Wrappers.<MemberPeopleExt>lambdaQuery().eq(MemberPeopleExt::getPeopleCode,memberPeople.getPeopleCode())) ;
                            b.setPeopleCode(memberPeople.getPeopleCode());
                            memberPeopleExtDao.insert(b);
                        }
                );
        /** 3，部门信息做修改 */
        Optional.ofNullable(memberPeopleDTO.getOrg()).map(a -> modelMapper.map(a, MemberPeopleOrg.class))
                .ifPresent(b -> {
                    memberPeopleOrgDao.delete(Wrappers.<MemberPeopleOrg>lambdaQuery().eq(MemberPeopleOrg::getPeopleCode,memberPeople.getPeopleCode()));
                    memberPeopleOrgDao.insert(b);
                });
    }

    private void checkSuperAdminDel(List<MemberPeopleAccount> memberPeopleAccount) {
        long count = memberPeopleAccount.stream().filter(account -> StrUtil.equals(account.getUserName(), CommonConstrant.SUPER_ADMIN)).count();
        if (count > 0) {
            throw new MemberException(super_admin_not_delete);
        }
    }

    @Override
    public void del(long id) {
        /** 检索人员是否存在 */
        MemberPeople memberPeople = getById(id);
        if (ObjectUtil.isNull(memberPeople)) {
            throw new MemberException(people_not_exist);
        }
        /** 删除账户信息表 */
        List<MemberPeopleAccount> memberPeopleAccount = accountDao.selectList(Wrappers.<MemberPeopleAccount>lambdaQuery().eq(MemberPeopleAccount::getPeopleCode, memberPeople.getPeopleCode()));
        if (CollectionUtil.isNotEmpty(memberPeopleAccount)) {
            /** 超管不能删除 */
            checkSuperAdminDel(memberPeopleAccount);
            for (int i = 0; i < memberPeopleAccount.size(); i++) {
                rbacAccountFeign.delete(memberPeopleAccount.get(i).getUserName());
            }
        }
        transactionTemplate.executeWithoutResult((transactionStatus) -> {
            /** 删除人员账户表 */
            accountDao.delete(Wrappers.<MemberPeopleAccount>lambdaQuery().eq(MemberPeopleAccount::getPeopleCode, memberPeople.getPeopleCode()));
            /** 删除基本信息表 */
            removeById(id);
            /** 删除扩展信息表 */
            memberPeopleExtDao.delete(Wrappers.<MemberPeopleExt>lambdaQuery().eq(MemberPeopleExt::getPeopleCode, memberPeople.getPeopleCode()));
            /** 删除组织人员信息表 */
            memberPeopleOrgDao.delete(Wrappers.<MemberPeopleOrg>lambdaQuery().eq(MemberPeopleOrg::getPeopleCode, memberPeople.getPeopleCode()));
        });
    }

    @Override
    public MemberPeopleVO getMemberPeople(long id) {
        MemberPeopleVO memberPeopleVO = new MemberPeopleVO();
        MemberPeopleBaseInfoDTO baseInfoDTO = memberPeopleDao.getPeopleInfo(id);
        if (ObjectUtil.isNull(baseInfoDTO)) {
            throw new MemberException(people_not_exist);
        }
        String peopleCode = baseInfoDTO.getPeopleCode();
        MemberPeopleAccount memberPeopleAccount = accountDao.selectOne(Wrappers.<MemberPeopleAccount>lambdaQuery().eq(MemberPeopleAccount::getPeopleCode, peopleCode));
        MemberPeopleExt memberPeopleExt = memberPeopleExtDao.selectOne(Wrappers.<MemberPeopleExt>lambdaQuery().eq(MemberPeopleExt::getPeopleCode, peopleCode));
        if (memberPeopleExt == null) {
            memberPeopleExt = new MemberPeopleExt();
        }
        List<MemberPeopleOrgBO> orgInfo = memberPeopleOrgDao.getOrgInfo(peopleCode);
        Optional.ofNullable(baseInfoDTO).ifPresent(base -> memberPeopleVO.setBase(base));
        Optional.ofNullable(memberPeopleExt).map(ext -> modelMapper.map(ext, MemberPeopleExtDTO.class))
                .ifPresent(dto -> memberPeopleVO.setExt(dto));
        Optional.ofNullable(memberPeopleAccount).map(account -> modelMapper.map(account, MemberPeopleAccountDTO.class))
                .ifPresent(dto -> memberPeopleVO.setAccount(dto));
        Optional.ofNullable(orgInfo).map(org -> buildPeopleOrgInfo(org))
                .ifPresent(dto -> memberPeopleVO.setOrg(dto));
        return memberPeopleVO;
    }

    @Override
    public PeopleInfo getPeopleInfo(String userName) {
        PeopleInfo peopleInfoByLogin = memberPeopleDao.getPeopleInfoByLogin(userName);
        if (ObjectUtil.isNotNull(peopleInfoByLogin) && StrUtil.isNotBlank(peopleInfoByLogin.getDeptCode())) {
            MemberDepartment memberDepartment = memberDepartmentDao.selectOne(Wrappers.<MemberDepartment>lambdaQuery().select(MemberDepartment::getDepartmentNumber).eq(MemberDepartment::getCode, peopleInfoByLogin.getDeptCode()));
            peopleInfoByLogin.setDepartmentNumber(memberDepartment.getDepartmentNumber());
        }
        return peopleInfoByLogin;
    }

    /**
     * 构建人员部门信息，可能存在多个部门信息
     *
     * @param bos
     * @return
     */
    private MemberPeopleOrgDTO buildPeopleOrgInfo(List<MemberPeopleOrgBO> bos) {
        MemberPeopleOrgDTO orgDTO = new MemberPeopleOrgDTO();
        String departmentName = bos.stream().map(MemberPeopleOrgBO::getDepartmentName).collect(Collectors.joining(","));
        String orgCode = bos.stream().map(MemberPeopleOrgBO::getOrgCode).collect(Collectors.joining(","));
        Optional.ofNullable(CollectionUtil.getFirst(bos)).ifPresent(a -> {
            MemberPeopleOrgBO peopleOrgBO = CollectionUtil.getFirst(bos);
            orgDTO.setDepartmentName(departmentName);
            orgDTO.setOrgCode(orgCode);
            orgDTO.setPeopleCode(peopleOrgBO.getPeopleCode());
        });
        return orgDTO;
    }

}
